home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 98 / Skunkware 98.iso / osr5 / sco / scripts / cbase < prev    next >
Encoding:
Korn shell script  |  1997-08-26  |  5.1 KB  |  189 lines

  1. #!/bin/ksh
  2. # @(#) cbase.ksh 1.3 97/07/13
  3. # 11/08/90 john h. dubois iii (john@armory.com)
  4. # 91/02/13 cleaned up
  5. # 91/04/29 changed incorrect reference to xbase() to cbase()
  6. # 93/07/12 Added oO options and ksh input bases.
  7. # 94/01/01 Changed [oO] to [rR], added bBoOxX options.
  8. # 94/11/11 Added w, and W, and s options.
  9. # 95/07/25 Added i option.
  10. # 97/07/13 Send error messages to stderr.
  11.  
  12. alias istrue="test 0 -ne"
  13. alias isfalse="test 0 -eq"
  14.  
  15. # Usage: SplitWord wordsize value
  16. # Low bits are put in SplitWord[0], etc.
  17. # The number of words put in SplitWord[] is returned
  18. # (this is one more than the highest index in SplitWord[])
  19. typeset -i SplitWord
  20. function SplitWord {
  21.     typeset -i WordSize=$1 Value=$2 i=0 Mask ShiftMask
  22.  
  23.     unset SplitWord[*]
  24.     ((Mask=(1<<WordSize)-1))    # Mask for getting low WordSize bits
  25.     # ShiftMask is used to get rid of the 1s that are shifted in for negative
  26.     # numbers.
  27.     (( ShiftMask=~(Mask<<(32-WordSize)) ))
  28.     while [ Value -ne 0 ]; do
  29.     ((SplitWord[i]=Value&Mask))
  30.     ((Value=(Value>>WordSize)&ShiftMask))
  31.     let i+=1
  32.     done
  33.     return $i
  34. }
  35.  
  36. # cbase: convert C-style and ksh-style constants to decimal numbers
  37. # convert hex (0xn and 0Xn), octal (0n), decimal or default, ksh (b#n)
  38. # to decimal & print
  39. # Globals: if defBase is set to a positive value, it is the default base
  40. # to use for values that are not hex or ksh-base constants.
  41. # If defBase is not set, values of the form 0n are taken to be octal;
  42. # if it is set, they are taken to be values in the default base.
  43. cbase() {
  44.     typeset -i$obase d
  45.     typeset -i i words Inc
  46.     typeset bits out
  47.  
  48.     while [ $# -gt 0 ]; do
  49.     if [[ defBase -gt 0 && "$1" = +([0-9a-zA-Z]) ]]; then
  50.         d=$defBase#$1 || {
  51.         shift
  52.         continue
  53.         }
  54.     else
  55.         case $1 in
  56.         0[xX]*([0-9a-fA-F]) ) d=16#${1#0[xX]};;    # C style hex
  57.         0*([0-7]) ) d=8#$1;;            # C style octal
  58.         [1-9]*([0-9]) ) d=$1;;            # decimal default
  59.         +([0-9])#+([0-9]) ) d=$1;;        # ksh style base
  60.         *) print -ru2 -- "$name: Bad number: $1"
  61.            shift
  62.            continue
  63.            ;;
  64.         esac
  65.     fi
  66.     if [ WordSize -lt 32 ]; then
  67.         SplitWord $WordSize $d
  68.         words=$?
  69.         if istrue BigEndian; then
  70.         Start=words-1
  71.         End=-1
  72.         Inc=-1
  73.         else
  74.         Start=0
  75.         End=words
  76.         Inc=1
  77.         fi
  78.         bits=
  79.         while [ Start -ne End ]; do
  80.         d=SplitWord[Start]
  81.         istrue nobase &&
  82.         bits="$bits$Sep${d#+([0-9])#}" || bits="$bits$Sep$d"
  83.         let Start+=Inc
  84.         done
  85.         out="$out ${bits#?}"    # get rid of initial Sep
  86.     else
  87.         istrue nobase && out="$out ${d#+([0-9])#}" || out="$out $d"
  88.     fi
  89.     shift
  90.     done
  91.     [ -n "$out" ] && print -- $out
  92. }
  93.  
  94. typeset -i obase=10 nobase=0 WordSize=32 BigEndian=0 defBase=0
  95. Sep=' '
  96.  
  97. name=${0##*/}
  98. Usage=\
  99. "Usage: $name [-hbBoOxX] [-i<in-base>] [-[rR]<out-base>] <integer value> ..."
  100.  
  101. while getopts :hr:R:bBoOxXw:W:s:i: opt; do
  102.     case $opt in
  103.     h)
  104.     print -r -- \
  105. "$name: convert integers between bases.
  106. $Usage
  107. Octal, decimal, and hexadecimal values may be given using C notation (nnn,
  108. 0nnn, and 0xnnn/0Xnnn)  respectively).  A value may also be entered in any base
  109. between 2 and 2^32-1 using ksh notation (base#value, e.g. 7#33 to enter a
  110. value in base 7).
  111. If no numbers are given on the command line, they are read from the input
  112. until end of file is reached.
  113. Options:
  114. -h: Print this help.
  115. -r<out-base>: Change the output base (radix) to <base>; must be in range 2..36.
  116. -b: Change the output base to 2 (binary).
  117. -o: Change the output base to 8 (octal).
  118. -x: Change the output base to 16 (hex).
  119. -R<out-base>, -B, -O, -X: Like the lower case options, except that the output
  120.     will not include base specifiers.
  121. -i<in-base>: Change the default input base from decimal to <in-base>.  This
  122.     affects values not given in hex (0xnnn) or ksh (b#nnn) notation.  If -i is
  123.     given, values that begin with 0 are taken to be in the specified base,
  124.     rather than octal.
  125. -w<wordsize>: Change the word size to <wordsize> bits.  Any values entered
  126.     which have more than <wordsize> bits will be split up into multiple words.
  127.     The word representing the high <wordsize> bits is printed first, but the
  128.     word is split starting from the right, which affects the grouping of
  129.     bits when <wordsize> is not a power of two.
  130. -W<wordsize>: Like -w, but the word representing the low <wordsize> bits is
  131.     printed first.
  132. -s<sep>: Set the separator string for words split according to the w and W
  133.     options.  By default, the components are separated with a space."
  134.     exit 0
  135.     ;;
  136.     i)
  137.     defBase=$OPTARG || exit 1
  138.     ;;
  139.     [rR])
  140.     obase=$OPTARG || exit 1
  141.     ;;
  142.     [bB])
  143.     obase=2
  144.     ;;
  145.     [oO])
  146.     obase=8
  147.     ;;
  148.     [xX])
  149.     obase=16
  150.     ;;
  151.     [wW])
  152.     WordSize=$OPTARG || exit 1
  153.     if [ WordSize -lt 1 ]; then
  154.         print -ru2 -- "$name: Bad word size: $OPTARG"
  155.         exit 1
  156.     fi
  157.     [ $opt = w ] && BigEndian=1
  158.     ;;
  159.     s)
  160.     Sep=$OPTARG;;
  161.     +?)
  162.     print -ru2 -- "$name: options should not be preceded by a '+'."
  163.     exit 1
  164.     ;;
  165.     :) 
  166.     print -ru2 -- \
  167.     "$name: Option '$OPTARG' requires a value.  Use -h for help."
  168.     exit 1
  169.     ;;
  170.     ?) 
  171.     print -ru2 -- "$name: $OPTARG: bad option.  Use -h for help."
  172.     exit 1
  173.     ;;
  174.     esac
  175.     [[ $opt = [A-Z] ]] && nobase=1
  176. done
  177.  
  178. # remove args that were options
  179. let OPTIND=OPTIND-1
  180. shift $OPTIND
  181.  
  182. if [ $# -gt 0 ]; then
  183.     cbase $*
  184. else
  185.     while read line; do
  186.     cbase $line
  187.     done
  188. fi
  189.